package com.sxr.spring.tenant;

import com.sxr.integration.TenantContext;
import com.sxr.integration.tenant.TenantConfigProvider;
import com.sxr.spring.SxrFileSignatureProperties;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 基于Spring Boot配置属性的租户配置提供者
 * 直接从application.yml等配置文件中读取租户配置
 * 支持热更新和动态配置
 *
 * @author SXR
 * @since 1.0.0
 */
public class SpringBootTenantConfigProvider implements TenantConfigProvider {

    private final SxrFileSignatureProperties properties;
    private final Map<String, TenantContext> tenantContextCache = new ConcurrentHashMap<>();

    public SpringBootTenantConfigProvider(SxrFileSignatureProperties properties) {
        this.properties = properties;
        initializeTenantContexts();
    }

    @Override
    public TenantContext getTenantContext(String tenantId) {
        // 先从缓存获取
        TenantContext context = tenantContextCache.get(tenantId);
        if (context != null) {
            return context;
        }

        // 如果缓存中没有，尝试从配置中构建
        return buildTenantContext(tenantId);
    }

    @Override
    public boolean refresh() {
        return false;
    }


    /**
     * 初始化租户上下文
     */
    private void initializeTenantContexts() {
        Map<String, SxrFileSignatureProperties.TenantConfig> tenantConfigs = properties.getTenants();

        if (tenantConfigs == null || tenantConfigs.isEmpty()) {
            return;
        }

        for (Map.Entry<String, SxrFileSignatureProperties.TenantConfig> entry : tenantConfigs.entrySet()) {
            String tenantId = entry.getKey();
            SxrFileSignatureProperties.TenantConfig config = entry.getValue();

            TenantContext context = buildTenantContextFromConfig(tenantId, config);
            tenantContextCache.put(tenantId, context);
        }

    }

    /**
     * 从配置构建租户上下文
     */
    private TenantContext buildTenantContext(String tenantId) {
        SxrFileSignatureProperties.TenantConfig config = properties.getTenants().get(tenantId);
        if (config == null) {
            return null;
        }

        TenantContext context = buildTenantContextFromConfig(tenantId, config);
        tenantContextCache.put(tenantId, context);
        return context;
    }

    /**
     * 从Spring Boot配置构建租户上下文
     */
    private TenantContext buildTenantContextFromConfig(String tenantId, SxrFileSignatureProperties.TenantConfig config) {
        TenantContext context = new TenantContext(tenantId);

        // 设置租户名称
        context.setTenantName(config.getName() != null ? config.getName() : tenantId);

        // 设置密钥，如果没有配置则使用默认密钥
        context.setSecretKey(config.getSecretKey() != null ? config.getSecretKey() : properties.getDefaultSecretKey());

        // 设置基础路径，如果没有配置则使用默认路径 + 租户ID
        String basePath = config.getBasePath();
        if (basePath == null) {
            basePath = properties.getBasePath() + "/" + tenantId;
        }
        context.setBasePath(basePath);


        // 设置最大文件大小
        context.setMaxFileSize(config.getMaxFileSize() != null ?
            config.getMaxFileSize() : properties.getMaxFileSize());

        // 设置白名单的扩展名
        List<String> whiteExtensions = config.getWhiteExtensions();
        if (whiteExtensions != null && !whiteExtensions.isEmpty()) {
            context.setWhiteExtensions(whiteExtensions.toArray(new String[0]));
        }


        // 设置允许的扩展名
        List<String> allowedExtensions = config.getAllowedExtensions();
        if (allowedExtensions != null && !allowedExtensions.isEmpty()) {
            context.setAllowedExtensions(allowedExtensions.toArray(new String[0]));
        }

        // 设置禁止的扩展名
        List<String> forbiddenExtensions = config.getForbiddenExtensions();
        if (forbiddenExtensions != null && !forbiddenExtensions.isEmpty()) {
            context.setForbiddenExtensions(forbiddenExtensions.toArray(new String[0]));
        }

        // 设置限流配置
        context.setEnableRateLimit(config.getEnableRateLimit() != null ?
            config.getEnableRateLimit() : false);
        context.setMaxRequestsPerSecond(config.getMaxRequestsPerSecond() != null ?
            config.getMaxRequestsPerSecond() : 100);

        return context;
    }

}
